/*
 ------------------------------------------------------------------------------
	sdlmedia - a test program for a media search library, including test UI.

	Copyright (C) 2011 Pierre Veber
	
	This program is free software; you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation; either version 3 of the License, or
	(at your option) any later version.
	
	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.
	
	You should have received a copy of the GNU General Public License
	along with this program; if not, write to the Free Software Foundation,
	Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
------------------------------------------------------------------------------
*/

#include "common.h"
#include "fastheap.h"
#include "sdlmedia.h"
#include "id3.h"

/* include mad stuff */
#include "mad/id3tag.h"
#pragma comment(lib, "../common/mad/libid3tag.lib")

/* libid3tag unexported definitions */
# ifdef __cplusplus
extern "C" {
# endif
id3_length_t id3_ucs4_utf16size(id3_ucs4_t const *);
id3_length_t id3_ucs4_length(id3_ucs4_t const *);
void id3_utf16_encode(id3_utf16_t *, id3_ucs4_t const *);
# ifdef __cplusplus
}
# endif

#define THIS_FILTER	TRACE_ID3

static int _id3_utf16_eq(Uint16* p1, Uint16* p2)
{
	while ( (*p1 != 0) && (*p2 != 0) )
	{
		if (*p1++ != *p2++)
		{
			return 0;
		}
	}
	return 1;
}

static int _id3_get_utf16_value(FastHeap_t* pHeap, id3_frame* pID3Frame, Uint16** ppVal)
{
	const id3_ucs4_t* pUCS4 = NULL;
	int nSize, nLen = 0;

	for (unsigned int ui=0; (ui < pID3Frame->nfields) && (pUCS4 == NULL); ui++)
	{
		id3_field* pID3Field = id3_frame_field(pID3Frame, ui);
		switch (id3_field_type(pID3Field))
		{
			case ID3_FIELD_TYPE_STRINGLIST:
				pUCS4 = id3_field_getstrings(pID3Field, 0);
				break;

			case ID3_FIELD_TYPE_STRING:
				pUCS4 = id3_field_getstring(pID3Field);
				break;

			default:
				//TRACE("_id3_get_utf16_value() - unsupported field type %d.\n", (int)id3_field_type(pID3Field));
				break;
		}
	}

	if (pUCS4 != NULL)
	{
		nSize = id3_ucs4_utf16size(pUCS4);
		*ppVal = (Uint16*)_fast_heap_alloc(pHeap, nSize*sizeof(Uint16));
		if (*ppVal != NULL)
		{
			id3_utf16_encode(*ppVal, pUCS4);
			nLen = id3_ucs4_length(pUCS4);
		}
	}
		
	return nLen;
}

 SDL_Surface* _id3_get_album_picture(const char* pszFilePath)
{
	id3_file* pID3File;
	id3_tag* pID3Tag;
	id3_frame* pID3Frame;
	id3_field* pBinary;
	
	SDL_Surface* pOut = NULL;

	/* get ID3 tags */
	pID3File = id3_file_open(pszFilePath, ID3_FILE_MODE_READONLY);
	if (pID3File == NULL)
	{
		TRACE("_id3_get_album_picture() - Unable to open id3: %S !\n", pszFilePath);
		return NULL;
	}

	pID3Tag = id3_file_tag(pID3File);
	if (pID3Tag == NULL)
	{
		TRACE("_id3_get_album_picture() - Unable to get id3 tag in %S !\n", pszFilePath);
		id3_file_close(pID3File);
		return NULL;
	}

	pID3Frame = id3_tag_findframe(pID3Tag, "APIC", pID3Tag->nframes);
	if ( (pID3Frame == NULL) || (pID3Frame->nfields < 5) )
	{
		TRACE("_id3_get_album_picture() - Unable to get id3 tag in %S !\n", pszFilePath);
		id3_file_close(pID3File);
		return NULL;
	}

	/* picture type */
	if (id3_field_getint(id3_frame_field(pID3Frame, 2)) == 3)
	{
		/* check mime type */
		const unsigned char* pszMime = id3_field_getlatin1(id3_frame_field(pID3Frame, 1));
		if (	(strcmp((const char *)pszMime, "image/png") != 0)
			 && (strcmp((const char *)pszMime, "image/jpeg") != 0)	)
		{
			TRACE("_id3_get_album_picture() - unsupported image format %S in %S!\n", (const char*)pszMime, pszFilePath);
			id3_file_close(pID3File);
			return NULL;
		}

		/* binary data */
		pBinary = id3_frame_field(pID3Frame, 4);
		if (pBinary != NULL)
		{
			SDL_RWops* pOps = SDL_RWFromConstMem(pBinary->binary.data, pBinary->binary.length);
			if (pOps != NULL)
			{
				pOut = IMG_Load_RW(pOps, 1);
			}
		}
	}

	id3_file_close(pID3File);
	return pOut;
}

int _id3_get_info(FastHeap_t* pHeap, const char* pszFilePath, MediaInfo_t* pInfo)
{
	id3_file* pID3File;
	id3_tag* pID3Tag;
	id3_frame* pID3Frame;

	/* get ID3 tags */
	pID3File = id3_file_open(pszFilePath, ID3_FILE_MODE_READONLY);
	if (pID3File == 0)
	{
		TRACE("_id3_get_info() - Unable to open id3: %S !\n", pszFilePath);
		return -1;
	}

	pID3Tag = id3_file_tag(pID3File);
	for (int i=0; i < (int)pID3Tag->nframes; i++)
	{
		pID3Frame = pID3Tag->frames[i];
		if (strcmp("TIT2", pID3Frame->id) == 0)
		{
			/* track title */
			_id3_get_utf16_value(pHeap, pID3Frame, &(pInfo->pszTrack));
			continue;
		}
		if (strcmp("TALB", pID3Frame->id) == 0)
		{
			/* album title */
			_id3_get_utf16_value(pHeap, pID3Frame, &(pInfo->pszAlbum));
			continue;
		}
		if (strcmp("TRCK", pID3Frame->id) == 0)
		{
			/* track number */
			_id3_get_utf16_value(pHeap, pID3Frame, &(pInfo->pszTrackNum));
			continue;
		}
		if (strcmp("TPE1", pID3Frame->id) == 0)
		{
			/* artist name */
			_id3_get_utf16_value(pHeap, pID3Frame, &(pInfo->pszArtist));
			continue;
		}
		if (strcmp("TLEN", pID3Frame->id) == 0)
		{
			/* length of track in ms */
			_id3_get_utf16_value(pHeap, pID3Frame, &(pInfo->pszMsLength));
			continue;
		}
		if (	(strcmp("TDRC", pID3Frame->id) == 0)
			 || (strcmp("TYER", pID3Frame->id) == 0)	)
		{
			/* release date */
			_id3_get_utf16_value(pHeap, pID3Frame, &(pInfo->pszYear));
			continue;
		}
		/*
			To do:
				RVA2?
				EQU2?
				RBUF?
				ASPI
		*/
	}

	id3_file_close(pID3File);

	return 0;
}
